#include "BloqueInterno.h"
#include <sstream>
#include "BloqueHoja.h"
#include "../../FuncionesUtiles.h"
#include "ManipuladorVector.h"

BloqueInterno::BloqueInterno(Arbol* a, cantBytes tamanio, TipoClave* extractor) :
	BloqueArbol(a, tamanio, extractor) {

	this->tipo = 'I';
	this->extractor = extractor;
	this->setPadre(ID_NULL);
}

BloqueInterno::~BloqueInterno() {

}

char BloqueInterno::getTipo() {

	return this->tipo;
}

Bytes BloqueInterno::serializarse() {
	/*tipo|id|padre|claves|punteros*/

	Bytes serializacion;

	serializacion.agregarAlFinal(&this->tipo, sizeof(this->tipo));

	serializacion.agregarAlFinal(&this->id, sizeof(this->id));

	serializacion.agregarAlFinal(&this->padre, sizeof(this->padre));

	serializacion.agregarAlFinal(BloqueArbol::serializarse());

	if (serializacion.getTamanio() < this->tamanio) {
		serializacion.agregarAlFinal(crearBytesNulos(this->tamanio
				- serializacion.getTamanio()));
	}

	return serializacion;
}

bool BloqueInterno::hidratarse(const Bytes& bytes) {
	/*tipo|id|padre|claves|punteros*/

	offset offsetActual = 0;
	bytes.leer(&this->tipo, offsetActual, sizeof(this->tipo));

	offsetActual += sizeof(this->tipo);

	bytes.leer(&this->id, offsetActual, sizeof(this->id));

	offsetActual += sizeof(this->id);

	bytes.leer(&this->padre, offsetActual, sizeof(this->padre));
	offsetActual += sizeof(this->padre);

	BloqueArbol::hidratarse(bytes.getSubBytes(offsetActual, bytes.getTamanio()
			- offsetActual));

	return false;
}

BloqueArbol* BloqueInterno::getHijoMenor() {
	return arbol->get(this->punteros[0])->getHijoMenor();
}

void BloqueInterno::addUltimoHijo(offset hijo) {
	this->punteros.push_back(hijo);
	this->setModificado();
}
int BloqueInterno::getPosicionVector(offset hijo) {
	unsigned i;
	for (i = 0; i < getPunteros().size(); i++) {
		if (hijo == getPunteros()[i]) {
			return i;
		}
	}
	return i;
}
BloqueArbol* BloqueInterno::getHijoDerecho(offset hijoIzquierdo) {
	std::vector<offset> hijos = this->getPunteros();
	/*menos uno puesto que puede ser el ultimo y no devuelvo algo q no existe*/
	for (unsigned i = 0; i < (hijos.size() - 1); i++) {
		if (hijoIzquierdo == hijos[i]) {
			return arbol->get(hijos[i + 1]);
		}
	}
	return NULL;
}

BloqueArbol* BloqueInterno::getHijoDerDer(const Key& claveVieja) {

	unsigned posicion = claves.size() - 2;
	BloqueArbol* hijoConClave = buscarUnHijo(claveVieja, posicion);

	if (hijoConClave == NULL || posicion > (claves.size() - 2)) {
		return NULL; /*No lo puedo tener*/
	}

	return arbol->get(punteros[posicion + 2]);
}

BloqueArbol* BloqueInterno::getHijoIzquierdo(offset hijo) {
	std::vector<offset> punteros = this->getPunteros();

	for (int i = (punteros.size() - 1); i >= 0; i--) {
		BloqueArbol* temp = arbol->get(punteros[i]);
		if ((temp->getClaves().size() == 0) && (i != 0)) {
			return arbol->get(punteros[i - 1]);
		}
		if (hijo == punteros[i]) {
			return (i == 0) ? NULL : arbol->get(punteros[i - 1]);
		}
	}
	return NULL;
}

BloqueArbol* BloqueInterno::getHijoDerecho(const Key& claveVieja) {
	unsigned posicion = claves.size() - 1;
	BloqueArbol* hijoConClave = buscarUnHijo(claveVieja, posicion);

	if (hijoConClave == NULL || posicion == (claves.size())) {
		return NULL; /*No lo puedo tener*/
	}
	return arbol->get(punteros[posicion + 1]);

}
BloqueArbol* BloqueInterno::getHijoIzquierdo(const Key& claveVieja) {
	unsigned posicion = 0;
	BloqueArbol* hijoConClave = buscarUnHijo(claveVieja, posicion);
	if (hijoConClave == NULL || posicion == 0) {
		return NULL; /*No lo puedo tener*/
	}
	return arbol->get(punteros[posicion - 1]);
}

BloqueArbol* BloqueInterno::getHijoIzqIzq(const Key& claveVieja) {

	unsigned posicion = 0;
		BloqueArbol* hijoConClave = buscarUnHijo(claveVieja, posicion);

		if (hijoConClave == NULL || posicion < 2) {
			return NULL; /*No lo puedo tener*/
		}

		return arbol->get(punteros[posicion - 2]);
}

BloqueInterno* BloqueInterno::mergeRaizHoja(BloqueHoja* hermanoIzq,
		BloqueHoja* nodo, BloqueHoja* hermano, Resultado res) {

	BloqueInterno* nodoPadre = this;
	Key claveAnterior = nodo->getClaveMayor();

	BalancearTres(hermanoIzq, nodo, hermano, false);

	nodoPadre->setModificado();

	res = nodoPadre->addClaveEHijo(hermanoIzq->getClaveMayor(),
			hermanoIzq->getId());
	res = nodoPadre->addClaveEHijo(nodo->getClaveMayor(), nodo->getId());
	nodoPadre->addUltimoHijo(hermano->getId());

	hermanoIzq->setPadre(nodoPadre->getId());
	nodo->setPadre(nodoPadre->getId());
	hermano->setPadre(nodoPadre->getId());

	nodo->setHermano(hermano->getId());
	offset viejo = nodoPadre->getId();
	this->arbol->setRaiz(nodoPadre->getId());

	nodoPadre->nuevosHijos(viejo);
	hermanoIzq->setHermano(viejo);

	return nodoPadre;

}

/*si puede balancear (quedan ambos nodos en estado valido), lo hace
 * y retorna true, sino puede retorna false*/
/*PRE: debe recibirlos en el orden que se balancearan*/
/*ojo solo se usa para Overflow, no under*/
bool BloqueInterno::balancearDosInternos(BloqueInterno* nodo,
		BloqueInterno* nodoHermano) {
	/*voy a poder mergear esos 2 hermanos y ninguno dara overflow*/
	if (!(nodo->existeOverflow(nodoHermano->claves.size()))) {

		BalancearDos(nodo, nodoHermano, false);
		int posicion = 0;
		/*posicion no indica nada, es de retorno*/
		nodo->removerClave(nodo->getClaveMayor(), posicion);

		nodo->nuevosHijos();
		nodoHermano->nuevosHijos();
		nodo->actualizarClaves();
		nodoHermano->actualizarClaves();

		nodo->setModificado();
		nodoHermano->setModificado();
		BloqueHoja* hoja = dynamic_cast<BloqueHoja*> (arbol->get(
				nodo->getPunteros()[0]));
		if (hoja != NULL) {

			for (unsigned i = 0; i < nodo->getPunteros().size(); i++) {

				hoja = dynamic_cast<BloqueHoja*> (arbol->get(
						nodo->getPunteros()[i]));
				hoja->actualizarSiguiente();

			}
		}

		/* debo cambiar la clave en el padre*/

		return true;
	}
	return false;

}
/*si puede balancear (quedan ambos nodos en estado valido), lo hace
 * y retorna true, sino puede retorna false*/
/*PRE: debe recibirlos en el orden que se balancearan*/
/*ojo solo se usa para underflow*/
bool BloqueInterno::mergeDosInternos(BloqueInterno* nodo,
		BloqueInterno* nodoHermano) {
	Key claveAnterior;
	if (nodo->claves.size() != 0) {
		claveAnterior = nodo->getClaveMayor();
	}
	/*voy a poder mergear esos 2 hermanos y ninguno dara overflow*/
	if (!nodo->existeUnderflow(nodoHermano->claves.size())) {

		BalancearDos(nodo, nodoHermano, false);

		/* debo cambiar la clave en el padre*/
		BloqueInterno* papa = dynamic_cast<BloqueInterno*> (arbol->get(
				nodo->getPadre()));
		if (nodo->claves.size() != 0) {

			papa->actualizarClaves();
			nodo->actualizarClaves();
			nodoHermano->actualizarClaves();

			nodo->setModificado();
			nodoHermano->setModificado();
			papa->setModificado();
			return true;

		}
		Key claveMayorDeMenores = nodo->getMayorDeRama();
		papa->cambiarClave(claveAnterior, claveMayorDeMenores);
		papa->setModificado();
		return true;
	}
	return false;
}

bool BloqueInterno::dosAUno(BloqueInterno* nodoHermano) {

	BloqueInterno* nodo = this;

	/*voy a poder mergear esos 2 hermanos y no dara overflow*/
	if (!nodo->existeOverflow(nodoHermano->getClaves().size())) {
		BalancearDos(nodo, nodoHermano, true);
		/* debo cambiar la clave en el padre*/
		nodoHermano->actualizarClaves();
		nodo->setBorrado();
		nodoHermano->setModificado();

		return true;
	}

	return false;
}

Resultado BloqueInterno::mergeTresInternos(BloqueInterno* hermanoIzq,
		BloqueInterno* nodo, BloqueInterno* hermano, bool tresADos) {

	Key claveAnteriorIzq;
	bool teniaClaveIzq = false;
	if (hermanoIzq->getCantClaves() != 0) {
		claveAnteriorIzq = hermanoIzq->getClaveMayor();
		teniaClaveIzq = true;
	}
	Key claveAnteriorMedio;

	if (nodo->getCantClaves() != 0) {
		claveAnteriorMedio = nodo->getClaveMayor();
	}

	BalancearTres(hermanoIzq, nodo, hermano, tresADos);

	hermanoIzq->nuevosHijos();
	nodo->nuevosHijos();
	hermano->nuevosHijos();
	hermanoIzq->actualizarClaves();
	if (!tresADos) {
		nodo->actualizarClaves();
	}
	hermano->actualizarClaves();
	/* debo cambiar la clave en el padre*/

	Key claveNueva = hermanoIzq->getMayorDeRama();

	if (tresADos) {
		nodo->setBorrado();
	}

	BloqueInterno* papa = dynamic_cast<BloqueInterno*> (arbol->get(
			hermanoIzq->getPadre()));
	if (teniaClaveIzq) {
		papa->actualizarClaves();
		papa->setModificado();
	}

	Resultado res;

	if (!tresADos) {

		nodo->setPadre(papa->getId());
		res = papa->addClaveEHijo(nodo->getClaveMayor(), nodo->getId());
		papa->actualizarClaves();
		papa->setModificado();
	}
	return res;
}

Key BloqueInterno::getMayorDeRama() {
	bool encontro = false;
	unsigned i = punteros.size();
	while (i > 0 && !encontro) {
		if (!arbol->get(punteros[i - 1])->getBorrado()) {
			encontro = true;
		}
		i--;
	}
	return arbol->get(punteros[i])->getMayorDeRama();
}

BloqueInterno* BloqueInterno::overflowRaizInterno(Resultado& res) {
	/*no tiene padre y por lo tanto no tiene ningun hermano, es la raiz */
	BloqueInterno* nodoHermano = dynamic_cast<BloqueInterno*> (arbol->getNew(
			'I'));
	BloqueInterno* nodo = this;
	if (nodo->getPadre() != ID_NULL) {
		std::cerr << "padre es distinto de null y no deberia serlo" << __FILE__
				<< __LINE__ << std::endl;
	}
	if (BloqueInterno::balancearDosInternos(nodo, nodoHermano)) {

		Resultado resultadohijo = RES_OK;
		BloqueInterno* nodoPadre = dynamic_cast<BloqueInterno*> (arbol->getNew(
				'I'));

		nodoPadre->addUltimoHijo(nodoHermano->getId());
		nodo->setPadre(nodoPadre->getId());
		nodoHermano->setPadre(nodoPadre->getId());
		Key claveMayorDeMenores = nodo->getMayorDeRama();
		nodo->setModificado();
		nodoPadre->setModificado();
		nodoHermano->setModificado();

		resultadohijo = nodoPadre->addClaveEHijo(claveMayorDeMenores,
				nodo->getId());
		nodoPadre->setPadre(ID_NULL);

		/*ahora los nuevos hijos de nodo y de nodohermano deberan apuntar a su nuevo padre*/
		nodoHermano->nuevosHijos();
		nodo->nuevosHijos();

		offset viejo = nodoPadre->getId();
		offset viejo2 = nodo->getId();
		this->arbol->setRaiz(nodoPadre->getId());

		nodoPadre->nuevosHijos(viejo);
		nodo->nuevosHijos(viejo2);
		nodo->actualizarClaves();
		nodoHermano->actualizarClaves();
		nodoPadre->actualizarClaves();

		return nodoPadre;
	}
	return NULL;
}

void BloqueInterno::overflowInterno(Resultado& res) {
	/*tengo este nodo, veo su hermano de la derecha, si se pueden repartir las claves de forma tal de que no queden
	 * en overflow, redestribuyo las claves.
	 * */
	BloqueInterno* nodo = this;

	BloqueInterno* padre = dynamic_cast<BloqueInterno*> (arbol->get(
			nodo->getPadre()));
	if (padre != NULL) {
		/*tiene un padre => tiene hermano/s */
		BloqueInterno* hermano =
				dynamic_cast<BloqueInterno*> (padre->getHijoDerecho(
						nodo->getId()));
		/*intento con un solo hermano, si no puedo debere usar el de la izquiera*/
		Key claveAnterior = nodo->getClaveMayor();

		if (hermano != NULL) {
			if (balancearDosInternos(nodo, hermano)) {
				Key claveNueva = nodo->getClaveMayor();
				BloqueInterno* papa = dynamic_cast<BloqueInterno*> (arbol->get(
						(nodo->getPadre())));
				papa->cambiarClave(claveAnterior, claveNueva);
				papa->setModificado();
			} else {
				/*no se pudieron balancear y por lo tanto creare un nuevo nodo que ira entremedio de los dos nodos*/

				BloqueInterno* nuevoNodo =
						dynamic_cast<BloqueInterno*> (arbol->getNew('I'));
				res = BloqueInterno::mergeTresInternos(nodo, nuevoNodo,
						hermano, false);

			}
		} else {
			BloqueInterno* hermano =
					dynamic_cast<BloqueInterno*> (padre->getHijoIzquierdo(
							nodo->getId()));
			/*intento con el hermano izquierdo*/
			if (hermano != NULL) {
				if (balancearDosInternos(hermano, nodo)) {
					BloqueInterno* papa =
							dynamic_cast<BloqueInterno*> (arbol->get(
									(nodo->getPadre())));
					papa->actualizarClaves();
					papa->setModificado();
				} else {

					/*no se pudieron balancear y por lo tanto creare un nuevo nodo que ira entremedio de los dos nodos*/
					BloqueInterno* nuevoNodo =
							dynamic_cast<BloqueInterno*> (arbol->getNew('I'));
					res = BloqueInterno::mergeTresInternos(hermano, nuevoNodo,
							nodo, false);

				}
			}

		}

	}
}

void BloqueInterno::resolverUnderflow(Resultado& res, const Key& claveBorrada) {
	BloqueInterno* nodo = this;

	BloqueInterno* padre = dynamic_cast<BloqueInterno*> (arbol->get(
			nodo->getPadre()));
	if (padre == NULL) { /*no tiene padre y por lo tanto no tiene ningun hermano, es la raiz */
		/*NO HAGO NADA, NO EXISTE UNDERFLOW PARA LA RAIZ*/
		if (this->claves.size() == 0) {
			this->setBorrado();
		}
	} else {
		/*tiene un padre => tiene hermano/s */
		/*THIS es el padre del nodo que explota*/

		BloqueInterno * hermano =
				dynamic_cast<BloqueInterno*> (padre->getHijoDerecho(
						claveBorrada));

		/*intento con un solo hermano, si no puedo debere usar el de la izquiera*/
		if (hermano != NULL) {/*tiene hermano derecho*/

			if (mergeDosInternos(nodo, hermano)) {
				nodo->nuevosHijos();
				hermano->nuevosHijos();
				res = RES_OK;
			} else {
				/*NO se mergiaron*/
				/*intento mergear con el de la izquierda*/
				BloqueInterno * hermanoIzq =
						dynamic_cast<BloqueInterno*> (padre->getHijoIzquierdo(
								claveBorrada));
				if (hermanoIzq != NULL) { /*tiene hermano izquierdo*/
					if (mergeDosInternos(hermanoIzq, nodo)) {
						nodo->nuevosHijos();
						hermanoIzq->nuevosHijos();
					} else {
						/*NO se mergiaron*/
						/*Existen mis dos hermanos y no me pude mergear con ninguno, por lo que
						 * de los tres me quedare con solamente dos completos*/
						res
								= mergeTresInternos(hermanoIzq, nodo, hermano,
										true);
						nodo->nuevosHijos();
						hermano->nuevosHijos();
						hermanoIzq->nuevosHijos();
					}
				} else {/*tengo hermano derecho pero no izquierdo intento con el derecho del derecho*/
					BloqueInterno * hermanoDer =
							dynamic_cast<BloqueInterno*> (padre->getHijoDerecho(
									hermano->getClaveMayor()));

					if (hermanoDer != NULL) {
						/*existe*/
						res	= mergeTresInternos(nodo, hermano, hermanoDer,
										true);


						nodo->nuevosHijos();
						hermano->nuevosHijos();
						hermanoDer->nuevosHijos();

					} else {

						if (nodo->getCantClaves() == 0) {
							nodo->dosAUno(hermano);
						} else {
							if (this->dosAUno(hermano)) {
								hermano->nuevosHijos();
							} else {
								std::cerr
										<< "dos nodos en underflow que no se pueden unir en uno solo"
										<< __FILE__ << __LINE__ << std::endl;
							}
						}
					}
				}
			}
		} else {
			/*no tengo hermano derecho*/
			/*intento mergear con el de la izquierda*/
			BloqueInterno* hermanoIzq =
					dynamic_cast<BloqueInterno*> (padre->getHijoIzquierdo(
							claveBorrada));
			if (hermanoIzq != NULL) { /*tiene hermano izquierdo*/
				if (mergeDosInternos(hermanoIzq, nodo)) {
					nodo->nuevosHijos();
					hermanoIzq->nuevosHijos();

				} else {
					BloqueInterno * hermanoIzqIzq =
							dynamic_cast<BloqueInterno*> (padre->getHijoIzqIzq(
									claveBorrada));

					if (hermanoIzqIzq != NULL) {
						/*existe*/
						res = mergeTresInternos(hermanoIzqIzq, hermanoIzq,
								nodo, true);
						nodo->nuevosHijos();
						hermanoIzq->nuevosHijos();
						hermanoIzqIzq->nuevosHijos();

					} else {
						if (nodo->getCantClaves() == 0) {
							nodo->dosAUno(hermanoIzq);
						} else {
							if (!this->dosAUno(hermanoIzq)) {
								std::cerr
										<< "dos nodos en underflow que no se pueden unir en uno solo"
										<< __FILE__ << __LINE__ << std::endl;
							}
						}

					}
				}
			}
		}
	}
}

/*Se inserta un elemento en el hijo correspondiente*/
BloqueArbol* BloqueInterno::insertarElemento(const Elemento& elemento,
		Resultado& res, bool &overflow) {
	BloqueArbol* donde = this->buscarHijo(elemento.getClave());
	donde->insertarElemento(elemento, res, overflow);
	/*se retorna de la llamada recursiva */
	this->actualizarClaves();
	return this;
}
bool BloqueInterno::tengoClave(Key clave) {
	unsigned tam = this->getCantClaves();
	for (unsigned int i = 0; i < tam; i++) {

		if (this->claves[i] == clave) {
			return true;
		}
	}
	return false;
}

/*lo unico que hace es enviarselo recursivamente a su hijo*/
BloqueArbol* BloqueInterno::removerElemento(const Elemento& elemento,
		Resultado& res) {
	Key claveABorrar = elemento.getClave();
	unsigned posicion = 0;
	BloqueArbol* donde = this->buscarUnHijo(claveABorrar, posicion);
	donde->removerElemento(elemento, res);
	/*se retorna de la llamada recursiva */

		BloqueArbol* temp = NULL;
		for (unsigned i = 0; i < this->punteros.size(); i++) {
			temp = arbol->get(punteros[i]);
			if (temp->getBorrado()) {
				dynamic_cast<BloqueInterno*> (this)->removerClaveEHijo(
								this->claves[i], temp);
				this->actualizarClaves();
				this->setModificado();
			}

		}


		if ((this->id == ID_RAIZ) && (this->getCantClaves() == 0)) {
					this->setBorrado();
					for(unsigned i = 0;i < this->punteros.size();i++){
					BloqueArbol* bloque=arbol->get(punteros[i]);
						if(bloque->getCantClaves() != 0){
						this->arbol->setRaiz(bloque->getId());
						if(bloque->getTipo() != 'H'){
						this->arbol->getRaiz()->nuevosHijos();
						}
						}
					}
				}
		if (tengoClave(claveABorrar)) {
			/*la reemplazo*/
			this->actualizarClaves();
			this->setModificado();
		}

	return this;
}

offset BloqueInterno::getElemento(const Key& clave, Resultado& res) {
	unsigned i = 0;
	Key aux1(0);
	bool encontrado = false;
	BloqueArbol* temp;
	while ((!encontrado) && (i < this->getCantClaves())) {

		aux1 = this->getClaves()[i];
		if (clave <= aux1) {
			encontrado = true;
			temp = arbol->get(punteros[i]);
			return (temp)->getElemento(clave, res);
		}
		i++;
	}
	if (i == 0) {
		std::cerr << "NUNCA DEBERia PASAR ESTO" << __FILE__ << __LINE__
				<< std::endl;
	}
	/*es el ultimo hijo*/
	temp = arbol->get(punteros[i]);
	return (temp)->getElemento(clave, res);
}

BloqueArbol* BloqueInterno::buscarHijo(const Key& claveABuscar) {
	unsigned i = 0;
	BloqueArbol* temp;
	bool encontrado = false;
	while ((!encontrado) && (i < this->getCantClaves())) {

		Key aux1 = (this->getClaves())[i];
		if (claveABuscar <= aux1) {
			encontrado = true;
			temp = arbol->get(punteros[i]);
			return temp->buscarHijo(claveABuscar);
		}
		i++;
	}
	if (i == 0) {
		std::cerr
				<< "NUNCA DEBERia PASAR ESTO(no tener ningun hijo siendo interno)"
				<< __FILE__ << __LINE__ << std::endl;
	}
	/*es el ultimo hijo*/
	temp = arbol->get(punteros[i]);
	return temp->buscarHijo(claveABuscar);
}

BloqueArbol* BloqueInterno::buscarUnHijo(const Key& claveABuscar,
		unsigned& posicion) {
	unsigned i = 0;
	bool encontrado = false;
	while ((!encontrado) && (i < this->getCantClaves())) {
		Key aux1 = claves[i];

		if (claveABuscar <= aux1) {
			encontrado = true;
			posicion = i;
			return arbol->get(punteros[i]);
		}
		i++;
	}
	if (i == 0) {
		std::cerr << "el vector no tiene hijos" << __FILE__ << __LINE__
				<< std::endl;
	}
	/*es el ultimo hijo*/
	posicion = i;
	return arbol->get(punteros[i]);
}
Resultado BloqueInterno::addClave(const Key& clave, int& posicion) {

	bool agregado = false;
	int i = 0;
	int cantClaves = claves.size();
	while ((!agregado) && (i < cantClaves)) {
		if (clave < claves[i]) {
			agregado = true;
			/*agrego en posicion i y los que estaban de i hasta size-1 deben moverse*/
			posicion = i;
			ManipuladorVector::agregarClaveVector<Key>(clave, i, this->claves);
			this->setModificado();
			return RES_OK;
		} else {
			if (clave == claves[i]) {
				/*LA CLAVE SE ENCUENTRA DUPLICADA*/
				return RES_DUPLICADO;
			}
		}
		i++;
	}
	if (!agregado) {
		/*es el ultimo*/
		this->claves.push_back(clave);
		posicion = i;
	}
	this->setModificado();
	return RES_OK;
}

BloqueInterno* BloqueInterno::resolverOverflow() {
	Resultado res;
	if (this->getPadre() == ID_NULL) {
		if (this->claves.size() == (2 * this->getCantClavesMax())) {

			/*esta hoja que exploto es la raiz*/

			BloqueInterno* nuevoPadre = this->overflowRaizInterno(res);
			return nuevoPadre;
		}
		return NULL;
	}
	/*la hoja que explota tiene hermanos*/
	this->overflowInterno(res);
	return NULL;

}

Resultado BloqueInterno::addClaveEHijo(const Key &clave, offset hijo) {

	/*no necesitpo el flag de overflow...Â¿?*/
	int posicion;

	Resultado res = addClave(clave, posicion);
	if (res == RES_OK) {
		ManipuladorVector::agregarClaveVector<offset>(hijo, posicion,
				this->punteros);
	}
	if (getCantClaves() > this->getCantClavesMax()) {
		/*tuve overflow, se lo aviso a mi papa, PERO yo resulvo mi overflow*/
		/*le avisa asi el se fija en que estado quedo el*/
		this->resolverOverflow();
	}
	this->setModificado();
	return res;
}

Resultado BloqueInterno::removerClaveEHijo(const Key &clave, BloqueArbol* hijo) {
	/*CUANDO REMUEVO UNA CLAVE EN LA POSICION N EL HIJO ES EL CORRRESPONDIENTE AL N+1
	 agregado en pos +1 */

	int posicion;
	Key c(clave);
	Resultado res = removerClave(c, posicion);

	if (res == RES_OK) {

		this->removerHijo(c);
		if (this->getId() == ID_RAIZ) {
			this->actualizarClaves();
			if (this->claves.size() == 0) {
				this->setBorrado();
			}
		}

		if ((this->getId() != ID_RAIZ) && (getCantClaves()
				< this->getCantClavesMin())) {

			this->resolverUnderflow(res, c);
		}
	}

	this->setModificado();
	return res;
}
void BloqueInterno::removerHijo(const Key &claveVieja) {

	BloqueArbol* temp;
	for (unsigned i = 0; i < this->punteros.size(); i++) {
		temp = arbol->get(punteros[i]);
		if (temp->getCantClaves() == 0) {
			ManipuladorVector::borrarClaveVector<offset>(i, this->punteros);
		}
	}
	this->setModificado();

}
Resultado BloqueInterno::removerClave(const Key& clave,
		int& posicionDondeAgregar) {

	bool borrado = false;
	int posicion = 0;
	int cantClaves = claves.size();
	while ((!borrado) && (posicion < cantClaves)) {
		if (clave == (this->claves[posicion])) {
			borrado = true;
			posicionDondeAgregar = posicion;
			/*borro la clave de la posicion i y los que estaban de i+1 hasta size-1 deben moverse*/
			ManipuladorVector::borrarClaveVector<Key>(posicion, this->claves);
		}
		posicion++;
	}
	if (!borrado) { /*no le encontrÃ³*/
		return RES_INEXISTENTE;
	}
	this->setModificado();
	return RES_OK;
}

std::string BloqueInterno::clavesToString() {

	std::stringstream st;
	st << "I (" << this->getId() << ", " << this->getPadre() << ")";

	for (unsigned i = 0; i < getCantClaves(); i++) {
		st << claves[i].toString() << "; ";

	}
	return st.str();
}

void BloqueInterno::imprimir() {
	unsigned tam = punteros.size();
	BloqueArbol* temp = NULL;
	for (unsigned i = 0; i < tam; ++i) {
		temp = arbol->get(punteros[i]);
		temp->imprimir();
	}
	std::cout << clavesToString() << std::endl;
}

